<?php

namespace App\Models;

use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Cache;

/**
 * 线上大赛模型
 * Class ArticleModel
 * @package app\common\model
 */
class CompetiteActivity extends BaseModel
{
    use HasFactory;

    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'change_time';

    protected $table = 'competite_activity';

    /*关联活动类型*/
    public function conType()
    {
        return $this->hasOne(CompetiteActivityType::class, 'id', 'type_id');
    }


    /**
     * 用户活动报名填写信息
     */
    public static function getCompetiteActivityApplyParam()
    {
        return [
            ['id' => 1, 'field' => 'username', 'value' => '作者'],
            ['id' => 2, 'field' => 'id_card', 'value' => '身份证'],
            ['id' => 7, 'field' => 'adviser', 'value' => '指导老师'], //性别  
            ['id' => 8, 'field' => 'adviser_tel', 'value' => '指导老师联系方式'], //年龄  
            ['id' => 3, 'field' => 'tel', 'value' => '电话号码'],
            ['id' => 4, 'field' => 'reader_id', 'value' => '读者证'],
            ['id' => 6, 'field' => 'unit', 'value' => '单位名称'], //单位名称  
            ['id' => 5, 'field' => 'wechat_number', 'value' => '微信号'], //备注  最多100字
            ['id' => 9, 'field' => 'age', 'value' => '年龄'], //年龄  数字
            ['id' => 10, 'field' => 'school', 'value' => '学校'], //学校  最多50字
            ['id' => 11, 'field' => 'participant', 'value' => '参赛者'], //参赛者  最多100字
            ['id' => 12, 'field' => 'original_work', 'value' => '原著'], //原著  最多50字
            // ['id' => 10, 'field' => 'accessory', 'value' => '附件'], //压缩包  最大3M  
        ];
    }
    /**
     * 检查活动报名填报信息
     * @param array $act_info 活动信息
     * @param array $real_info
     * @param $data 需要验证的真实信息id用|连接起来     1、作者   2 、身份证号码  3、电话号码   4、读者证号    5、微信号 6、单位名称 7、指导老师  8、指导老师联系方式  9 年龄 10 学校  11 参赛者 12 原著
     * @return array
     */
    public function checkApplyParam(array $real_info, array $data)
    {
        foreach ($real_info as $key => $val) {
            if ($val == 1) {
                if (empty($data['username']) || mb_strlen($data['username']) < 2) {
                    throw new Exception('作者名规则不正确');
                }
            } elseif ($val == 2) {
                if (empty($data['id_card']) || !is_legal_no($data['id_card'])) {
                    throw new Exception('身份证号码规则不正确');
                }
            } elseif ($val == 3) {
                if (empty($data['tel']) || !verify_tel($data['tel'])) {
                    throw new Exception('电话号码规则不正确');
                }
            } elseif ($val == 4) {
                if (empty($data['reader_id'])) {
                    throw new Exception('读者证不能为空');
                }
            } elseif ($val == 5) {
                if (empty($data['wechat_number'])) {
                    throw new Exception('微信号码不能为空');
                }
            } elseif ($val == 6) {
                if (empty($data['unit'])) {
                    throw new Exception('单位不能为空');
                }
            } elseif ($val == 7) {
                if (empty($data['adviser'])) {
                    throw new Exception('指导老师不能为空');
                }
            } elseif ($val == 8) {
                if (empty($data['adviser_tel']) || !verify_tel($data['adviser_tel'])) {
                    throw new Exception('指导老师联系方式不正确');
                }
            } elseif ($val == 9) {
                if (empty($data['age']) || !is_numeric($data['age'])) {
                    throw new Exception('年龄格式不正确');
                }
            } elseif ($val == 10) {
                if (empty($data['school'])) {
                    throw new Exception('学校不能为空');
                }
            } elseif ($val == 11) {
                if (empty($data['participant'])) {
                    throw new Exception('参赛者不能为空');
                }
            } elseif ($val == 12) {
                if (empty($data['original_work'])) {
                    throw new Exception('原著不能为空');
                }
            }
        }
        return true;
    }

    /**
     * 获取总浏览量
     * @param con_id 大赛id
     */
    public function getBrowseNumber($con_id)
    {
        return $this->where(function ($query) use ($con_id) {
            if ($con_id) {
                $query->where('con_id', $con_id);
            }
        })->where('is_del', 1)
            ->sum('browse_num');
    }


    /**
     * 更新浏览量
     *
     * @param con_id 大赛id  
     * @param number 多少次更新一次
     * @param second 大于秒更新一次（取决于后一次请求事件）
     */
    public function updateBrowseNumber($con_id, $number = 100, $second = 300)
    {
        if ($number == 1) {
            return $this->where('id', $con_id)->increment('browse_num', 1);
        }

        $key = $con_id . 'competite_activity_browse_number';
        $res = Cache::pull($key); //从缓存中获取缓存项然后删除，使用 pull 方法，如果缓存项不存在的话返回 null
        $data = [];
        if (empty($res)) {
            $data['number'] = 1;
            $data['create_time'] = time();
            Cache::put($key, $data, 3600 * 24);
        } else {
            //数据大于50或者时间超过5分钟，则更新一次数据
            if ($res['number'] >= $number || time() - $res['create_time'] >= $second) {
                return $this->where('id', $con_id)->increment('browse_num', $res['number'] + 1);
            } else {
                $data['number'] = $res['number'] + 1;
                $data['create_time'] = $res['create_time'];
                Cache::put($key, $data, 3600 * 24);
            }
        }
        return true;
    }


    /**
     * 列表
     * @param limit int 分页大小
     * @param type_id string 类型id
     * @param keywords string 搜索关键词(文章标题)
     * @param start_time datetime 比赛开始时间(开始)
     * @param end_time datetime 比赛结束时间(开始)
     * @param create_start_time datetime 活动创建开始时间   数据格式 年月日时分秒
     * @param create_end_time datetime 活动创建结束时间
     * @param is_play 是否发布 0全部  1 发布  2未发布
     */
    public function lists($field = null, $type_id = null, $keywords = null, $start_time = null, $end_time = null, $create_start_time = null, $create_end_time = null, $is_play = 1, $limit = 10)
    {
        //$manage_lib_ids = request()->manage_lib_ids;

        if (empty($field)) {
            $field = [
                'id', 'type_id', 'tag_id', 'node', 'title', 'app_img as img', 'host_handle', 'tel', 'con_start_time', 'con_end_time', 'vote_start_time',
                'vote_end_time', 'is_reader', 'vote_way', 'number'/* ,'originals','promise' */, 'intro', 'rule_content', 'is_play', 'create_time',
                'browse_num', 'deliver_way', 'appraise_way', 'manage_id','is_need_authorizations'
            ];
        }
        $res = $this->select($field)
            ->with('conType', function ($query) {
                $query->select('id', 'type_name')->where('is_del', 1);
            })->where(function ($query) use ($keywords) {
                $query->where('title', 'like', "%$keywords%");
            })->where(function ($query) use ($type_id, $is_play, $start_time, $end_time, $create_start_time, $create_end_time) {
                if ($type_id) {
                    $query->where('type_id', $type_id);
                }
                if ($is_play) {
                    $query->where('is_play', $is_play);
                }
                if ($start_time && $end_time) {
                    $query->whereBetween('con_start_time', [$start_time, $end_time]);
                }
                if ($create_start_time && $create_end_time) {
                    $query->whereBetween('create_time', [$create_start_time, $create_end_time]);
                }
            })
            ->where('is_del', 1)
            ->orderByDesc('con_start_time')
            ->paginate($limit)
            ->toArray();


        foreach ($res['data'] as $key => $val) {
            $res['data'][$key]['intro'] = str_replace('&nbsp;', '', strip_tags($val['intro']));
        }

        return $res;
    }

    /**
     * 详情
     * @param id 大赛id
     */
    public function detail($id, $field = null)
    {
        if (empty($field)) {
            $field = [
                'id', 'type_id', 'tag_id', 'title', 'app_img as img', 'host_handle', 'tel', 'contacts', 'con_start_time', 'con_end_time', 'vote_start_time', 'vote_end_time',
                'is_reader', 'vote_way', 'number', 'originals', 'real_info', 'intro', 'rule_content', 'create_time', 'promise', 'appraise_way', 'deliver_way',
                'check_manage_id','manage_id','is_need_authorizations','is_need_promise'
            ];
        }
        return $this->select($field)->with('conType', function ($query) {
            $query->select('id', 'type_name')->where('is_del', 1);
        })->where('is_del', 1)->find($id);
    }



    /**
     * 列表
     * @param type int 类型  1 个人账号  2 团队账号  当前是团队查询还是个人查询
     * @param user_id int 用户id
     * @param group_id int 团队id
     * @param limit int 分页大小
     * @param keywords string 搜索关键词(文章标题)
     * @param start_time datetime 比赛开始时间(开始)
     * @param end_time datetime 比赛结束时间(开始)
     * @param is_play 是否发布 0全部  1 发布  2未发布
     */
    public function myCompetiteLists($type, $group_id, $user_id, $keywords, $start_time, $end_time, $is_play = 1, $limit = 10)
    {
        $res = $this->from('competite_activity as c')
            ->select([
                'c.id', 'c.type_id', 'c.tag_id', 'c.title', 'c.app_img as img', 'c.host_handle', 'c.tel', 'c.contacts', 'c.con_start_time', 'c.con_end_time', 'c.vote_start_time',
                'c.vote_end_time', 'c.is_reader', 'c.vote_way', 'c.number', 'originals', 'promise', 'c.intro', 'c.rule_content', 'c.is_play', 'c.create_time',
                'appraise_way', 't.type_name'
            ])
            ->join('competite_activity_works as w', 'w.con_id', '=', 'c.id')
            ->leftjoin('competite_activity_type as t', 't.id', '=', 'c.type_id')
            ->where(function ($query) use ($keywords) {
                $query->where('c.title', 'like', "%$keywords%");
            })->where(function ($query) use ($is_play, $start_time, $end_time) {
                if ($is_play) {
                    $query->where('c.is_play', $is_play);
                }
                if ($start_time && $end_time) {
                    $query->whereBetween('c.con_start_time', [$start_time, $end_time]);
                }
            })
            ->where('c.is_del', 1)
            ->where('t.is_del', 1)
            ->where(function ($query) use ($type, $user_id, $group_id) {
                if ($type == 1) {
                    $query->where('type', 1);
                    if ($user_id) {
                        $query->where('user_id', $user_id);
                    }
                } elseif ($type == 2) {
                    $query->where('type', 2);
                    if ($group_id) {
                        $query->where('group_id', $group_id);
                    }
                }
            })
            ->where('w.status', '<>', 5) //不等于5，已删除
            ->groupBy('c.id')
            ->orderByDesc('id')
            ->paginate($limit)
            ->toArray();
        foreach ($res['data'] as $key => $val) {
            $res['data'][$key]['intro'] = strip_tags($val['intro']);
        }

        return $res;
    }
    /**
     * 根据类型获取类型下的最新数据
     * @param type_id
     */
    public function getCompetiteActivityByTypeId($type_id, $limit = 1)
    {
        $data = $this->select([
            'id', 'type_id', 'tag_id', 'title', 'app_img as img', 'host_handle', 'tel', 'contacts', 'con_start_time', 'con_end_time', 'vote_start_time',
            'vote_end_time', 'is_reader', 'vote_way', 'number', 'intro', 'create_time', 'appraise_way', 'browse_num','is_need_authorizations'
        ])->with('conType', function ($query) {
            $query->select('id', 'type_name')->where('is_del', 1);
        })->where('type_id', $type_id)
        ->where('is_del', 1)
        ->where('is_play', 1)
        ->where('con_end_time', '>' , date('Y-m-d H:i:s'))
        ->orderByDesc('id')
        ->limit($limit)
        ->get()
        ->toArray();

        foreach ($data as $key => $val) {
            $data[$key]['node'] = 2; //代表征集活动
            $data[$key]['intro'] = strip_tags($val['intro']); //列表状态
            $data[$key]['status'] = $this->getCompetiteStatus($val); //列表状态
            $data[$key]['type_name'] = isset($val['con_type']['type_name']) ? $val['con_type']['type_name'] : '';

            $data[$key]['con_start_time'] = date('Y-m-d H:i', strtotime($val['con_start_time']));
            $data[$key]['con_end_time'] = date('Y-m-d H:i', strtotime($val['con_end_time']));
            unset($data[$key]['con_type']);
        }
        return $data;
    }
    /**
     * 根据node 获取 对应值
     * @param node 上传文件类型，连接  1.图片(默认)  2.文字  3.音频  4.视频 5.PDF 多个逗号链接
     */
    public function getNodeName($node)
    {
        $node = explode(',', $node);
        if (empty($node)) {
            return "图片、文字、音频、视频、PDF";
        }
        $node_name = '';
        if (in_array(1, $node)) {
            $node_name .= '、' . '图片';
        }
        if (in_array(2, $node)) {
            $node_name .= '、' . '文字';
        }
        if (in_array(3, $node)) {
            $node_name .= '、' . '音频';
        }
        if (in_array(4, $node)) {
            $node_name .= '、' . '视频';
        }
        if (in_array(5, $node)) {
            $node_name .= '、' . 'PDF';
        }

        return trim($node_name, '、');
    }



    /**
     * 获取活动状态
     * $data 活动数组
     * 
     * $status 1.大赛未开始  2 投稿中  3 投票未开始  4 投票中  5 投票已结束  6 大赛已结束  7 评审未开始  8 评审中  9 评审已结束
     */
    public function getCompetiteStatus($data)
    {
        $time = date('Y-m-d H:i:s');
        if ($data['con_start_time'] > $time) {
            $status = 1;
        } else if ($data['con_start_time'] < $time && $data['con_end_time'] > $time) {
            $status = 2;
        } else if ($data['vote_start_time'] > $time && $data['con_end_time'] < $time) {
            $status = $data['appraise_way'] == 3 ? 7 : 3;
        } else if ($data['vote_start_time'] < $time && $data['vote_end_time'] > $time) {
            $status = $data['appraise_way'] == 3 ? 4 : 8;
        } else if ($data['vote_end_time'] < $time && $data['con_end_time'] > $time) {
            $status = $data['appraise_way'] == 3 ? 5 : 9;
        } else {
            $status = 6;
        }
        return $status;
    }

    /**
     * 判断当前活动是否有打分权限
     * @param $con_id 活动id
     */
    public function isCompetiteAcivityReviewScore($con_id)
    {
        $res = $this->where('id', $con_id)->where('is_del', 1)->value('appraise_way');
        if (empty($res) || $res == 2) {
            return false;
        }
        //获取自己是否在评审管理员里面
        $CompetiteActivityWorksTypeModel = new CompetiteActivityWorksType();
        $score_manage_id = $CompetiteActivityWorksTypeModel->where('con_id', $con_id)->where('is_del', 1)->pluck('score_manage_id');
        if (empty($score_manage_id) || !in_array(request()->manage_id, $score_manage_id)) {
            return false;
        }
        return true;
    }

    /**
     * 判断当前活动是否有审核
     * @param $con_id 活动id
     */
    public function isCompetiteAcivitySelfCheck($con_id)
    {
        $res = $this->where('id', $con_id)->where('is_del', 1)->value('check_manage_id');
        if (empty($res) || !in_array(request()->manage_id, explode(',', $res))) {
            return false;
        }
        return true;
    }


    /**
     * 获取正在进行中的活动
     */
    public function getUnderWay($limit = 1)
    {
        $res = $this->select([
            'id', 'node', 'title', 'web_img', 'app_img', 'host_handle', 'tel', 'con_start_time', 'con_end_time', 'vote_start_time',
            'vote_end_time', 'is_reader', 'vote_way', 'number'/* ,'originals','promise' */, 'intro', 'rule_content', 'is_play', 'create_time',
            'browse_num', 'deliver_way', 'appraise_way','is_need_authorizations'
        ])
            ->where('con_start_time', '<', date('Y-m-d H:i:s'))
            ->where('vote_end_time', '>', date('Y-m-d H:i:s'))
            ->where('is_del', 1)
            ->where('is_play', 1)
            ->orderByDesc('con_start_time')
            ->limit($limit)
            ->get()
            ->toArray();


        foreach ($res as $key => $val) {
            $res[$key]['intro'] = str_replace('&nbsp;', '', strip_tags($val['intro']));
        }
        return $res;
    }

    /**
     * 获取正在进行中的活动
     */
    public function getBeAboutToStart($limit = 1)
    {
        $res = $this->select([
            'id', 'node', 'title', 'web_img', 'app_img', 'host_handle', 'tel', 'con_start_time', 'con_end_time', 'vote_start_time',
            'vote_end_time', 'is_reader', 'vote_way', 'number'/* ,'originals','promise' */, 'intro', 'rule_content', 'is_play', 'create_time',
            'browse_num', 'deliver_way', 'appraise_way','is_need_authorizations'
        ])
            ->where('con_start_time', '>', date('Y-m-d H:i:s'))
            ->where('is_del', 1)
            ->where('is_play', 1)
            ->orderByDesc('con_start_time')
            ->limit($limit)
            ->get()
            ->toArray();
        foreach ($res as $key => $val) {
            $res[$key]['intro'] = str_replace('&nbsp;', '', strip_tags($val['intro']));
        }
        return $res;
    }

    /**
     * 大赛活动作品大类型统计
     * @param con_id 活动id
     * @param $start_time 活动开始时间
     * @param $end_time 活动结束时间
     */
    public function competiteActivityStatistics($con_id = null, $start_time = null, $end_time = null)
    {
        //分别统计4个活动的类型
        $CompetiteActivityWorksTypeModel = new CompetiteActivityWorksType();
        $type_data = $CompetiteActivityWorksTypeModel->worksType();
        $total_number = 0;
        $data = [];
        foreach ($type_data as $key => $val) {
            $data[$key]['name'] = $val['name'];
            $data[$key]['count'] = CompetiteActivityWorks::whereIn('status', [1, 2, 3])->where(function ($query) use ($con_id, $start_time, $end_time) {
                if ($con_id) {
                    $this->query('act_id', $con_id);
                }
                if ($start_time && $end_time) {
                    $query->whereBetween('create_time', [$start_time, $end_time]); //只按活动开始时间进行统计
                }
            })->whereNotNull($val['field_name'])->count();
            $total_number += $data[$key]['count'];
        }
        foreach ($data as $key => $val) {
            $data[$key]['proportion'] = $total_number ? sprintf("%.2f", $val['count'] / $total_number * 100) . '%' : '0%';
        }
        return $data;
    }
}
